package kevin.study.zephyr.domain.factory.document;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;

import kevin.study.zephyr.domain.factory.DocumentFactory;
import kevin.study.zephyr.domain.model.Document;
import kevin.study.zephyr.domain.model.Field;
import kevin.study.zephyr.domain.model.Form;
import kevin.study.zephyr.domain.model.Item;


/**
 * @author Kevin.Huang
 * @createtime 2007-12-12
 */
public class DefaultFactory implements DocumentFactory {

	public void indexItem(Document document) {
		Collection< Item > items = document.getItems();
		HashMap< String, Collection< Item >> indexItem = new HashMap< String, Collection< Item > >();
		document.setIndexItems(indexItem);
		if (items != null && !items.isEmpty()) {
			for (Item i : items) {
				if (!indexItem.keySet().contains(i.getField().getName())) {
					indexItem.put(i.getField().getName(), new ArrayList< Item >());
				}
				indexItem.get(i.getField().getName()).add(i);
			}
		}
	}

	public Document createDocument() {
		Document d = new Document();
		d.setItems(new ArrayList< Item >());
		indexItem(d);
		return d;
	}

	public Document createDocumentFromForm(Form form) {
		Document d = createDocument();
		d.setForm(form);
		formatDocumentByForm(d);
		indexItem(d);
		return d;
	}

	public void formatDocumentByForm(Document document) {
		Form form = document.getForm();
		if (form != null) {
			Collection< Field > fields = new HashSet< Field >();
			Collection< Form > forms = new HashSet< Form >();
			forms.add(form);
			getAllFieldFromForm(forms, fields);

			Collection< Item > itemNew = new ArrayList< Item >();
			Collection< Item > docItems = document.getItems();
			matchingFieldAndItem(fields, itemNew, docItems);
			addSpilthField(fields, itemNew);
			document.setItems(itemNew);
		}
	}

	/**
	 * @param fields
	 * @param itemNew
	 */
	private void addSpilthField(Collection< Field > fields, Collection< Item > itemNew) {
		for (Field f : fields) {
			Item i = new Item();
			i.setField(f);
			itemNew.add(i);
		}
	}

	/**
	 * @param fields
	 * @param itemNew
	 * @param docItems
	 */
	private void matchingFieldAndItem(Collection< Field > fields, Collection< Item > itemNew,
			Collection< Item > docItems) {
		if (docItems != null) {
			// 匹配
			for (Item i : docItems) {
				if (fields.contains(i.getField())) {
					fields.remove(i.getField());
					itemNew.add(i);
				}
			}
		}
	}

	private void getAllFieldFromForm(Collection< Form > forms, Collection< Field > fields) {
		if (forms != null && !forms.isEmpty()) {
			for (Form form : forms) {
				if (form.getFields() != null && !form.getFields().isEmpty()) {
					fields.addAll(form.getFields());
				}
				if (form.getSubForms() != null && !form.getSubForms().isEmpty()) {
					getAllFieldFromForm(form.getSubForms(), fields);
				}
			}
		}
	}

	public void injectItem(Document document, Collection< Item > items) {
		document.setItems(items);
		indexItem(document);
	}
}
